package com.itcast.zk.election;

import org.apache.zookeeper.*;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>Description: </p>
 *
 * @author
 * @version 1.0
 * <p>Copyright:Copyright(c)2020</p>
 * @date
 */
public class NonFairElection {
    
    /**
     * ZK连接地址
     */
    private static String connectAddr = "192.168.23.129:2181";
    
    /**
     * ZK客户端
     */
    private static ZooKeeper zk = null;
    /**
     * 连接超时时间（单位： 毫秒）
     */
    private static int sessionTimeout = 10000;
    
    public static void main(String[] args) throws Exception {
        // 服务编号
        String serverNo = "Leader" + 5;
        // 启动连接
        zk = new ZooKeeper(connectAddr, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(serverNo + " startup: " + event.getState());
            }
        });
        
        // 模拟服务器进行选举监听
        selection(serverNo);
        
        // 阻塞主线程
        TimeUnit.HOURS.sleep(1);
    }
    
    /**
     * 非公平选举处理流程
     *
     * @throws Exception
     */
    private static void selection(String serverNo) throws Exception {
        
        try {
            //1、创建选举节点
            zk.create("/master/election", serverNo.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            //2、没有异常代表创建成功
            System.out.println(serverNo + ": 选举成功");
        } catch (Exception e) {
            System.out.println(serverNo + ": 选举失败, " + e.getMessage());
        } finally {
            //3、监听节点
            zk.getData("/master/election", new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    System.out.println(serverNo + " 检测到节点变化，重新开始选举");
                    try {
                        // 4. 如果节点删除， 开始新一轮的选举
                        if (Objects.equals(event.getType(), Event.EventType.NodeDeleted)) {
                            selection(serverNo);
                        }
                    } catch (Exception e) {
                    }
                }
            }, null);
        }
    }
    
}
